isf 0.1.0

Parsing, Deserialization and Serialization of the Interactive Shader Format.
Documentation
/*{
    "CATEGORIES": [
        "Color Effect"
    ],
    "CREDIT": "by VIDVOX",
    "DESCRIPTION": "Creates variations on a base color using a given algorithm.",
    "INPUTS": [
        {
            "NAME": "inputImage",
            "TYPE": "image"
        },
        {
            "DEFAULT": 0,
            "LABEL": "Sample Mode",
            "LABELS": [
                "Base Color",
                "Pixel Follow",
                "Color Average"
            ],
            "NAME": "sampleMode",
            "TYPE": "long",
            "VALUES": [
                0,
                1,
                2
            ]
        },
        {
            "DEFAULT": 1,
            "LABEL": "Color Mode",
            "LABELS": [
                "Basic Complementary",
                "Split Complementary",
                "Compound Complementary",
                "Spectrum",
                "Shades",
                "Analogous",
                "Compound Analogous"
            ],
            "NAME": "colorModeOverride",
            "TYPE": "long",
            "VALUES": [
                0,
                1,
                2,
                3,
                4,
                5,
                6
            ]
        },
        {
            "DEFAULT": 7,
            "LABEL": "Color Count",
            "LABELS": [
                "2",
                "3",
                "4",
                "5",
                "6",
                "7",
                "8",
                "9",
                "10",
                "11",
                "12",
                "13",
                "14",
                "15",
                "16"
            ],
            "NAME": "colorCount",
            "TYPE": "long",
            "VALUES": [
                2,
                3,
                4,
                5,
                6,
                7,
                8,
                9,
                10,
                11,
                12,
                13,
                14,
                15,
                16
            ]
        },
        {
            "DEFAULT": [
                0.25,
                0.59,
                0.9,
                1
            ],
            "LABEL": "Base Color",
            "NAME": "baseColor",
            "TYPE": "color"
        },
        {
            "DEFAULT": [
                0.5,
                0.5
            ],
            "LABEL": "Pixel Point",
            "MAX": [
                1,
                1
            ],
            "MIN": [
                0,
                0
            ],
            "NAME": "pixelFollowLocation",
            "TYPE": "point2D"
        }
    ],
    "ISFVSN": "2",
    "PASSES": [
        {
            "HEIGHT": "$HEIGHT / 100.0",
            "TARGET": "bufferPassA",
            "WIDTH": "$WIDTH / 100.0"
        },
        {
            "HEIGHT": "1.0",
            "TARGET": "autoColorBuffer",
            "WIDTH": "1.0",
            "persistent": true
        },
        {
        }
    ]
}
*/




vec3 rgb2hsv(vec3 c)	{
	vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
	//vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
	//vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
	vec4 p = c.g < c.b ? vec4(c.bg, K.wz) : vec4(c.gb, K.xy);
	vec4 q = c.r < p.x ? vec4(p.xyw, c.r) : vec4(c.r, p.yzx);
	
	float d = q.x - min(q.w, q.y);
	float e = 1.0e-10;
	return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

vec3 hsv2rgb(vec3 c)	{
	vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
	vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
	return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

float gray(vec4 c)	{
	return (c.r + c.g + c.b) * c.a / 3.0;	
}

void main()
{
	if (PASSINDEX == 0)	{
		vec4 		inputColor = IMG_NORM_PIXEL(inputImage, isf_FragNormCoord);
		gl_FragColor = inputColor;
	}
	else if (PASSINDEX == 1)	{
		vec4 		inputColor = IMG_NORM_PIXEL(bufferPassA, isf_FragNormCoord);
		vec4 		oldColor = IMG_NORM_PIXEL(autoColorBuffer, vec2(0.5,0.5));
		gl_FragColor = mix(inputColor, oldColor, 0.8);
	}
	else if (PASSINDEX == 2)	{
		vec4 		inputColor = IMG_THIS_PIXEL(inputImage);
		vec4		inColor = baseColor;
		float		index = floor(gray(inputColor) * float(colorCount));	
		//float		index = floor(isf_FragNormCoord.x * float(colorCount));
		float		variation = 0.3236;	//	1/5 the golden ratio
		int			colorMode = colorModeOverride;

		if (sampleMode == 0)	{
			inColor = baseColor;
			inColor.rgb = rgb2hsv(inColor.rgb);
		}
		else if (sampleMode == 1)	{
			inColor = IMG_NORM_PIXEL(inputImage, pixelFollowLocation);
			inColor.rgb = rgb2hsv(inColor.rgb);
		}
		else if (sampleMode == 2)	{
			inColor = IMG_NORM_PIXEL(autoColorBuffer, vec2(0.5,0.5));
			inColor.rgb = rgb2hsv(inColor.rgb);
			if (inColor.b < 0.1)	{
				inColor = inColor * 1.5;	
			}
		}
	
		vec4		outColor = inColor;
	
		//	Basic complimentary  saturation and brightness variations on two fixed 180 degree opposite hues
		if (colorMode == 0)	{
			if (mod(index, 2.0) >= 1.0)	{
				outColor.r = outColor.r + 0.5;
				outColor.r = outColor.r - floor(outColor.r);
			}
		
			outColor.g = outColor.g - variation * floor(index / 2.0);
		
			if (outColor.g < 0.1)	{
				outColor.g = outColor.g + variation * floor(index / 2.0);
				outColor.g = outColor.g - floor(outColor.g);
			}
		
			outColor.b = outColor.b - variation * floor(index / 4.0);
			if (outColor.b < 0.2)	{
				outColor.b = outColor.b + variation * floor(index / 4.0);
				outColor.b = outColor.b - floor(outColor.b);
			}
		}
		//	Split complimentary  saturation and brightness variations on a 3 fixed 120 degree hues
		else if (colorMode == 1)	{
			float divisor = 3.0;
			float ratio = 0.45;
			if (mod(index, 3.0) >= 2.0)	{
				outColor.r = outColor.r - ratio;
			}
			else if (mod(index, 3.0) >= 1.0)	{
				outColor.r = outColor.r + ratio;
			}
		
			//outColor.g = outColor.g + variation * floor(index / divisor);
		
			if (mod(index, 5.0) >= 3.0)	{
				outColor.g = outColor.g - variation;
				outColor.g = outColor.g - floor(outColor.g);
			}
			outColor.b = outColor.b - variation * floor(index / (divisor));
			if (outColor.b < 0.1)	{
				outColor.b = outColor.b + variation * floor(index / (divisor));
				outColor.b = outColor.b - floor(outColor.b);
			}
		}
		//	Compound complimentary  a combination of shades, complimentary and analogous colors with slight shifts
		else if (colorMode == 2)	{
			if (mod(index, 3.0) >= 2.0)	{
				outColor.r = outColor.r + 0.5;
				outColor.r = outColor.r + variation * index * 1.0 / float(colorCount - 1) / 4.0;
			}
			else	{
				outColor.r = outColor.r + variation * index * 1.0 / float(colorCount - 1);
			}
			outColor.r = outColor.r - floor(outColor.r);
		
		
			if (mod(index, 2.0) >= 1.0)	{
				outColor.g = outColor.g + index * variation / 2.0;
			}
			else if (mod(index, 3.0) >= 2.0)	{
				outColor.g = outColor.g - variation / 2.0;
			}
			else	{
				outColor.g = outColor.g - index * variation / float(colorCount - 1);
			}
			if (outColor.g > 1.0)	{
				outColor.g = outColor.g - floor(outColor.g);
			}
		}
		//	Spectrum  hue shifts based on number of colors with minor saturation shifts
		else if (colorMode == 3)	{
			outColor.r = outColor.r + index * 1.0 / float(colorCount);
			if (mod(index, 3.0) >= 2.0)	{
				outColor.g = outColor.g - variation / 2.0;
				outColor.g = outColor.g - floor(outColor.g);
			}
			else if (mod(index, 4.0) >= 3.0)	{
				outColor.g = outColor.g + variation / 2.0;
				//outColor.g = outColor.g - floor(outColor.g);
			}
		}
		//	Shades  saturation and brightness variations on a single fixed hue
		else if (colorMode == 4)	{
			if (mod(index, 2.0) >= 1.0)	{
				outColor.b = outColor.b - (index * variation) / float(colorCount-1);
			}
			else	{
				outColor.b = outColor.b + (index * variation) / float(colorCount-1);
				outColor.b = outColor.b - floor(outColor.b);
			}
			if (outColor.b < 0.075)	{
				outColor.b = 1.0 - outColor.b * variation;
			}
		
			if (mod(index, 3.0) >= 2.0)	{
				outColor.g = outColor.g - (index * variation) / 2.0;
			}
			else if (mod(index, 4.0) >= 3.0)	{
				outColor.g = outColor.g + (index * variation) / 2.0;
			}
		
			if ((outColor.g > 1.0) || (outColor.g < 0.05))	{
				outColor.g = outColor.g - floor(outColor.g);
			}
		}
		//	Analogous  small hue and saturation shifts 
		else if (colorMode == 5)	{

			outColor.r = outColor.r + variation * index * 1.0 / float(colorCount - 1); 		

			if (mod(index, 3.0) >= 1.0)	{
				outColor.g = outColor.g - variation / 2.0;
				if (outColor.g < 0.0)	{
					outColor.g = outColor.g + variation / 2.0;
				}
				if (outColor.g > 1.0)	{
					outColor.g = outColor.g - floor(outColor.g);
				}
			}
		}
		//	Compound Analogous  similar to analogous but with negative hue shifts
		else if (colorMode == 6)	{
			if (mod(index, 3.0) >= 1.0)	{
				outColor.r = outColor.r + variation * index * 1.0 / float(colorCount - 1);
			}
			else	{
				outColor.r = outColor.r - variation * index * 0.5 / float(colorCount - 1);	
			}
			if (mod(index, 3.0) >= 1.0)	{
				outColor.g = outColor.g - variation / 2.0;
				if (outColor.g < 0.0)	{
					outColor.g = outColor.g + variation;
				}
				if (outColor.g > 1.0)	{
					outColor.g = outColor.g - floor(outColor.g);
				}
			}
			if (mod(index, 4.0) >= 2.0)	{
				if (outColor.b < variation)	{
					outColor.b = outColor.b + variation;
				}				
			}
		}
	
		gl_FragColor = vec4(hsv2rgb(outColor.rgb), inColor.a);
	}
}